﻿//=====================================================================================================
// LocalizationLibrary
// The Localization Library is a collection of reusable software component that provide 
// support for localization. This library enable you to localize WPF, Silverlight and WP7 applications.
// (http://localizationlibrary.codeplex.com)
//=====================================================================================================
// Author: Nicola Gallo (Website: www.nicola.gallo.name, Email: nicolagmt@hotmail.it) 
//=====================================================================================================

namespace LocalizationLibrary.Reflection
{
    //.NET References
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Reflection;

    /// <summary>
    /// Defines the class that manages the application's assembly.
    /// </summary>
    public class AssemblyManager
    {
        //Events

        /// <summary>
        /// Occurs when an assembly is loaded.
        /// </summary>
        public static event AssemblyLoadedEventHandler AssemblyLoaded;

        //Constructors

        /// <summary>
        /// Default static constructor.
        /// </summary>
        static AssemblyManager()
        {
            AssemblyManager.ReflectionCache = ReflectionCache.Create();
            AssemblyManager.DefaultAssembliesProvider = new AssembliesProvider();
#if SILVERLIGHT && (! WINDOWS_PHONE)

            AssemblyManager.LoadedDeploymentParts = new List<DeploymentPart>();
#endif
        }

        //Readonly properties

        /// <summary>
        /// Gets the default assemblies provider.
        /// </summary>
        private readonly static AssembliesProvider DefaultAssembliesProvider;

#if SILVERLIGHT && (! WINDOWS_PHONE)

        /// <summary>
        /// Gets the loaded <see cref="DeploymentPart"/>s.
        /// </summary>
        private readonly static List<DeploymentPart> LoadedDeploymentParts;

#endif

        /// <summary>
        /// Gets reflection cache.
        /// </summary>
        internal static ReflectionCache ReflectionCache;

        //Properties

        /// <summary>
        /// Gets the application's <see cref="AssembliesProvider"/>.
        /// </summary>
        public static AssembliesProvider AppAssembliesProvider { get; set; }

        //Methods

        /// <summary>
        /// Publishes the input <see cref="assembly"/> assembly.
        /// </summary>
        /// <param name="assembly"></param>
        protected internal static void PublishAssemblyLoaded(Assembly assembly)
        {
            if (assembly != null)
            {
                AssemblyLoadedEventHandler handler = AssemblyManager.AssemblyLoaded as AssemblyLoadedEventHandler;
                if (handler != null)
                {
                    handler(typeof(AssemblyManager).FullName, new AssemblyEventArgs(assembly));
                }
            }
        }

        /// <summary>
        /// Resets the <see cref="AssemblyManager"/>.
        /// </summary>
        public static void Reset()
        {
#if SILVERLIGHT && (! WINDOWS_PHONE)
            AssemblyManager.LoadedDeploymentParts.Clear();
#endif
            AssemblyManager.ReflectionCache = ReflectionCache.Create();
        }

#if SILVERLIGHT && WINDOWS_PHONE

        /// <summary>
        /// Gets the assemblies that have been loaded into the current deployment.
        /// </summary>
        /// <returns>An array of assemblies in this application domain.</returns>
        public static Assembly[] GetCurrentDeploymentAssemblies()
        {
            AssembliesProvider assembliesProvider = AssemblyManager.AppAssembliesProvider ?? AssemblyManager.DefaultAssembliesProvider;
            return assembliesProvider.GetCurrentDeploymentAssemblies();
        }

#elif SILVERLIGHT

        /// <summary>
        /// Gets the assemblies that have been loaded into the current deployment.
        /// application domain.
        /// </summary>
        /// <returns>An array of assemblies in this application domain.</returns>
        public static Assembly[] GetCurrentDeploymentAssemblies()
        {
            AssembliesProvider assembliesProvider = AssemblyManager.AppAssembliesProvider ?? AssemblyManager.DefaultAssembliesProvider;
            return assembliesProvider.GetCurrentDeploymentAssemblies();
        }

        /// <summary>
        /// Loads the input <see cref="deploymentPart"/> deployment part.
        /// </summary>
        /// <param name="deploymentPart">Deployment part to load.</param>
        /// <param name="deploymentPartKind">Kind of deploymentpart.</param>
        /// <returns>Loaded assemblies.</returns>
        /// <exception cref="ArgumentNullException">
        /// Thrown whether <paramref name="deploymentPart"/> parameter is null.
        /// </exception>
        public static void LoadAssemblies(DeploymentPart deploymentPart, DeploymentPartKind deploymentPartKind)
        {
            if (deploymentPart == null)
            {
                throw new ArgumentNullException("deploymentPart shouldn't be null.");
            }
            if (AssemblyManager.LoadedDeploymentParts.Contains(deploymentPart))
            {
                deploymentPart.GetAssemblies();
            }
            else
            {
                AssembliesProvider assembliesProvider = AssemblyManager.AppAssembliesProvider ?? AssemblyManager.DefaultAssembliesProvider;
                assembliesProvider.LoadAssemblies(deploymentPart, deploymentPartKind);
            }
        }

#else

        /// <summary>
        /// Gets the assemblies that have been loaded into the execution context of the input <see cref="appDomain"/>
        /// application domain.
        /// </summary>
        /// <returns>An array of assemblies in this application domain.</returns>
        public static Assembly[] GetCurrentDomainAssemblies()
        {
            AssembliesProvider assembliesProvider = AssemblyManager.AppAssembliesProvider ?? AssemblyManager.DefaultAssembliesProvider;
            return assembliesProvider.GetCurrentDomainAssemblies();
        }

        /// <summary>
        /// Gets the assemblies that have been loaded into the execution context of the input <see cref="appDomain"/>
        /// application domain.
        /// </summary>
        /// <param name="appDomain">Application domain.</param>
        /// <returns>An array of assemblies in this application domain.</returns>
        /// <exception cref="ArgumentNullException">
        /// Thrown whether <paramref name="appDomain"/> parameter is null.
        /// </exception>
        public static Assembly[] GetAssemblies(AppDomain appDomain) 
        {
            AssembliesProvider assembliesProvider = AssemblyManager.AppAssembliesProvider ?? AssemblyManager.DefaultAssembliesProvider;
            return assembliesProvider.GetAssemblies(appDomain);
        }

#endif
    }
}